Window: Focus custom titlebar with F10
authorPhillip Wood <phillip.wood@dunelm.org.uk>
Tue, 4 Mar 2014 11:06:30 +0000 (11:06 +0000)
committerMatthias Clasen <mclasen@redhat.com>
Mon, 10 Mar 2014 00:26:54 +0000 (20:26 -0400)
As discussed on desktop-devel-list [1], "There should be an intuitive,
consistent, immediate way to jump to the widgets that live in the
header bar." F10 has been suggested for this as it is already used to
active menubars.

F10 will focus the custom titlebar widget if the window has one and it
isn't already focused. If the titlebar widget doesn't exist or is
already focused then F10 focuses the menubar if there is one.

[1] https://mail.gnome.org/archives/desktop-devel-list/2014-February/msg00176.html

https://bugzilla.gnome.org/show_bug.cgi?id=725141

gtk/gtkmenubar.c
gtk/gtkmenubar.h
gtk/gtkwindow.c

index 3b5f7752e76369a6a0a02c00adec13af3e4f2c24..46aca862e2726368ed3d4c2b780538618c21e267 100644 (file)
@@ -656,8 +656,8 @@ get_menu_bars (GtkWindow *window)
   return g_object_get_data (G_OBJECT (window), "gtk-menu-bar-list");
 }
 
-static GList *
-get_viewable_menu_bars (GtkWindow *window)
+GList *
+_gtk_menu_bar_get_viewable_menu_bars (GtkWindow *window)
 {
   GList *menu_bars;
   GList *viewable_menu_bars = NULL;
@@ -691,76 +691,12 @@ set_menu_bars (GtkWindow *window,
   g_object_set_data (G_OBJECT (window), I_("gtk-menu-bar-list"), menubars);
 }
 
-static gboolean
-window_key_press_handler (GtkWidget   *widget,
-                          GdkEventKey *event,
-                          gpointer     data)
-{
-  gchar *accel = NULL;
-  gboolean retval = FALSE;
-
-  g_object_get (gtk_widget_get_settings (widget),
-                "gtk-menu-bar-accel", &accel,
-                NULL);
-
-  if (accel && *accel)
-    {
-      guint keyval = 0;
-      GdkModifierType mods = 0;
-
-      gtk_accelerator_parse (accel, &keyval, &mods);
-
-      if (keyval == 0)
-        g_warning ("Failed to parse menu bar accelerator '%s'\n", accel);
-
-      /* FIXME this is wrong, needs to be in the global accel resolution
-       * thing, to properly consider i18n etc., but that probably requires
-       * AccelGroup changes etc.
-       */
-      if (event->keyval == keyval &&
-          ((event->state & gtk_accelerator_get_default_mod_mask ()) ==
-          (mods & gtk_accelerator_get_default_mod_mask ())))
-        {
-          GList *tmp_menubars = get_viewable_menu_bars (GTK_WINDOW (widget));
-          GList *menubars;
-
-          menubars = _gtk_container_focus_sort (GTK_CONTAINER (widget), tmp_menubars,
-                                                GTK_DIR_TAB_FORWARD, NULL);
-          g_list_free (tmp_menubars);
-
-          if (menubars)
-            {
-              GtkMenuShell *menu_shell = GTK_MENU_SHELL (menubars->data);
-
-              _gtk_menu_shell_set_keyboard_mode (menu_shell, TRUE);
-              gtk_menu_shell_select_first (menu_shell, FALSE);
-
-              g_list_free (menubars);
-
-              retval = TRUE;
-            }
-        }
-    }
-
-  g_free (accel);
-
-  return retval;
-}
-
 static void
 add_to_window (GtkWindow  *window,
                GtkMenuBar *menubar)
 {
   GList *menubars = get_menu_bars (window);
 
-  if (!menubars)
-    {
-      g_signal_connect (window,
-                       "key-press-event",
-                       G_CALLBACK (window_key_press_handler),
-                       NULL);
-    }
-
   set_menu_bars (window, g_list_prepend (menubars, menubar));
 }
 
@@ -771,14 +707,6 @@ remove_from_window (GtkWindow  *window,
   GList *menubars = get_menu_bars (window);
 
   menubars = g_list_remove (menubars, menubar);
-
-  if (!menubars)
-    {
-      g_signal_handlers_disconnect_by_func (window,
-                                           window_key_press_handler,
-                                           NULL);
-    }
-
   set_menu_bars (window, menubars);
 }
 
@@ -816,7 +744,7 @@ _gtk_menu_bar_cycle_focus (GtkMenuBar       *menubar,
 
   if (gtk_widget_is_toplevel (toplevel))
     {
-      GList *tmp_menubars = get_viewable_menu_bars (GTK_WINDOW (toplevel));
+      GList *tmp_menubars = _gtk_menu_bar_get_viewable_menu_bars (GTK_WINDOW (toplevel));
       GList *menubars;
       GList *current;
 
index fc0e38b806d5af2ed5b3884c41d81222940f2c10..f1d71837c15f010551ebd93412442d1ef6436667 100644 (file)
@@ -88,6 +88,8 @@ void             gtk_menu_bar_set_child_pack_direction (GtkMenuBar       *menuba
 /* Private functions */
 void _gtk_menu_bar_cycle_focus (GtkMenuBar       *menubar,
                                GtkDirectionType  dir);
+GList* _gtk_menu_bar_get_viewable_menu_bars (GtkWindow *window);
+
 
 
 G_END_DECLS
index 68e6ffa80058564098e0a400a9c2b6655020529c..d996af13ebaa689302204a62805098c22f7597b7 100644 (file)
@@ -42,6 +42,7 @@
 #include "gtkmain.h"
 #include "gtkmnemonichash.h"
 #include "gtkmenubar.h"
+#include "gtkmenushellprivate.h"
 #include "gtkicontheme.h"
 #include "gtkmarshalers.h"
 #include "gtkplug.h"
@@ -11552,6 +11553,71 @@ gtk_window_parse_geometry (GtkWindow   *window,
   return result != 0;
 }
 
+static gboolean
+gtk_window_activate_menubar (GtkWindow   *window,
+                             GdkEventKey *event)
+{
+  GtkWindowPrivate *priv = window->priv;
+  gchar *accel = NULL;
+  guint keyval = 0;
+  GdkModifierType mods = 0;
+
+  g_object_get (gtk_widget_get_settings (GTK_WIDGET (window)),
+                "gtk-menu-bar-accel", &accel,
+                NULL);
+
+  if (accel == NULL || *accel == 0)
+    return FALSE;
+
+  gtk_accelerator_parse (accel, &keyval, &mods);
+  g_free (accel);
+
+  if (keyval == 0)
+    {
+      g_warning ("Failed to parse menu bar accelerator '%s'\n", accel);
+      return FALSE;
+    }
+
+  /* FIXME this is wrong, needs to be in the global accel resolution
+   * thing, to properly consider i18n etc., but that probably requires
+   * AccelGroup changes etc.
+   */
+  if (event->keyval == keyval &&
+      ((event->state & gtk_accelerator_get_default_mod_mask ()) ==
+       (mods & gtk_accelerator_get_default_mod_mask ())))
+    {
+      GList *tmp_menubars;
+      GList *menubars;
+      GtkMenuShell *menu_shell;
+
+      if (priv->title_box != NULL &&
+          !gtk_widget_is_ancestor (gtk_window_get_focus (window), priv->title_box) &&
+          gtk_widget_child_focus (priv->title_box, GTK_DIR_TAB_FORWARD))
+        return TRUE;
+
+      tmp_menubars = _gtk_menu_bar_get_viewable_menu_bars (window);
+      if (tmp_menubars == NULL)
+        return FALSE;
+
+      menubars = _gtk_container_focus_sort (GTK_CONTAINER (window), tmp_menubars,
+                                            GTK_DIR_TAB_FORWARD, NULL);
+      g_list_free (tmp_menubars);
+
+      if (menubars == NULL)
+        return FALSE;
+
+      menu_shell = GTK_MENU_SHELL (menubars->data);
+
+      _gtk_menu_shell_set_keyboard_mode (menu_shell, TRUE);
+      gtk_menu_shell_select_first (menu_shell, FALSE);
+
+      g_list_free (menubars);
+
+      return TRUE;
+    }
+  return FALSE;
+}
+
 static void
 gtk_window_mnemonic_hash_foreach (guint      keyval,
                                  GSList    *targets,
@@ -11775,7 +11841,7 @@ gtk_window_activate_key (GtkWindow   *window,
         }
     }
 
-  return FALSE;
+  return gtk_window_activate_menubar (window, event);
 }
 
 static void